package com.genius.framework.multitenancy.service;

import com.genius.framework.multitenancy.annotation.CommonScheduleTask;
import com.genius.framework.multitenancy.annotation.CommonScheduleTaskMethod;
import com.genius.framework.multitenancy.crontask.CronTaskRegister;
import com.genius.framework.multitenancy.crontask.SchedulingRunnable;
import com.genius.framework.multitenancy.entity.DynamicTask;
import com.genius.framework.multitenancy.util.SpringContextUtil;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.*;

@Service
public class ScheduleTaskService {

    @Autowired
    private CronTaskRegister cronTaskRegister;

    /**
     * 添加定时任务
     * @return taskKey
     */
    public String addTask(DynamicTask dynamicTask) {
        SchedulingRunnable task = new SchedulingRunnable(dynamicTask.getBeanName(), dynamicTask.getMethodName(), dynamicTask.getTaskParams());
        return cronTaskRegister.addCronTask(task, dynamicTask.getCronExpression());
    }

    /**
     * 执行一次任务
     * @param dynamicTask 任务参数实体
     */
    public void executeTask(DynamicTask dynamicTask) {
        SchedulingRunnable task = new SchedulingRunnable(dynamicTask.getBeanName(), dynamicTask.getMethodName(), dynamicTask.getTaskParams());
        task.run();
    }

    /**
     * 停止定时任务
     * @param taskKey 定时任务key
     */
    public void stopTask(String taskKey) {
        cronTaskRegister.removeCronTask(taskKey);
    }


    /**
     * 获取定时任务的类
     * @return
     */
    public List<Map<String, String>> getCommonScheduleTaskBean() {
        List<Map<String, String>> beans = new ArrayList<>();
        // 根据注解获取对应的类
        Map<String, Object> clazzMap = SpringContextUtil.getBeanByAnnotation(CommonScheduleTask.class);
        CommonScheduleTask beanTaskAnnotation;
        String beanDescription;
        Iterator<Map.Entry<String, Object>> iterator = clazzMap.entrySet().iterator();
        Map.Entry<String, Object> entry;
        Map<String, String> bean;
        while (iterator.hasNext()) {
            entry = iterator.next();
            bean = new HashMap<>();
            beanTaskAnnotation = entry.getValue().getClass().getAnnotation(CommonScheduleTask.class);
            if (beanTaskAnnotation.active()) {
                beanDescription = beanTaskAnnotation.description();
                bean.put("class", entry.getKey());
                bean.put("desc", "".equals(beanDescription) ? entry.getKey() : beanDescription);
                beans.add(bean);
            }
        }
        return beans;
    }

    /**
     * 获取定时任务类中的task方法
     * @return
     */
    public List<Map<String, Object>> getCommonScheduleTaskMethod(String className) {
        List<Map<String, Object>> methodArray = new ArrayList<>();
        Map<String, Object> methodParams;
        Object bean;
        try {
            // 获取task类
            bean = SpringContextUtil.getBean(className);
            // 获取类中定义的方法
            Method[] methods = bean.getClass().getDeclaredMethods();
            boolean isTaskMethod;
            List<String> params;
            String methodDescription;
            for (Method method : methods) {
                isTaskMethod = false;
                // 判断类上是否有定时任务方法的注解
                for (Annotation annotation : method.getDeclaredAnnotations()) {
                    if (annotation instanceof CommonScheduleTaskMethod) {
                        isTaskMethod = true;
                        break;
                    }
                }
                if (isTaskMethod) {
                    methodParams = new HashMap<>();
                    params = new ArrayList<>();
                    Class[] paramClazzs = method.getParameterTypes();
                    for (Class paramClazz : paramClazzs) {
                        params.add(paramClazz.getName());
                    }
                    // 获取方法的描述
                    methodDescription = method.getAnnotation(CommonScheduleTaskMethod.class).value();
                    methodParams.put("method", method.getName());
                    methodParams.put("desc", "".equals(methodDescription) ? method.getName() : methodDescription);
                    methodParams.put("params", params);
                    methodArray.add(methodParams);
                }
            }
        } catch (NoSuchBeanDefinitionException e) {
            return methodArray;
        }

        return methodArray;
    }
}
